package com.zsc.wxm.ysh.anjo.service.base.exception;

import com.zsc.wxm.ysh.anjo.result.CodeEnum;
import com.zsc.wxm.ysh.anjo.result.Result;
import com.zsc.wxm.ysh.anjo.utils.ExceptionUtil;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.validator.internal.engine.path.PathImpl;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * @author HP
 */
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    /**
     * 捕获断言异常
     *
     * @param e
     * @return
     */
    @ExceptionHandler(IllegalArgumentException.class)
    public Result illegalArgumentException(IllegalArgumentException e) {
        log.error(ExceptionUtil.getMessage(e));
        return Result.error(e.getMessage());
    }

    /**
     * 自定义异常
     *
     * @param e
     * @return
     */
    @ExceptionHandler(AnjoException.class)
    public Result anjoException(AnjoException e) {
        log.error(ExceptionUtil.getMessage(e));
        return Result.error(e.getMessage());
    }

    /**
     * JSR303 数据校验
     *
     * @param e
     * @return
     */
    @ExceptionHandler(ConstraintViolationException.class)
    public Result violationException(ConstraintViolationException e) {
        StringBuilder msg = new StringBuilder();
        Set<ConstraintViolation<?>> constraintViolations = e.getConstraintViolations();
        for (ConstraintViolation<?> violation : constraintViolations) {
            PathImpl path = (PathImpl) violation.getPropertyPath();
            String paramName = path.getLeafNode().getName();
            String message = violation.getMessage();
            msg.append("[").append("参数名称：").append(paramName)
                    .append(",")
                    .append(message)
                    .append("]");
        }
        log.error("数据校验异常，异常信息：{}", msg.toString());
        return Result.error(msg.toString());
    }

    /**
     * 数据校验异常(当@Valid 与 @RequestBody结合使用时，如果参数校验失败则触发该异常)
     *
     * @param e
     * @return
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Result handleValidException(MethodArgumentNotValidException e) {
        log.info("出现该异常MethodArgumentNotValidException");
        BindingResult bindingResult = e.getBindingResult();
        Map<String, Object> errorMessage = new HashMap<>();
        bindingResult.getFieldErrors().forEach(msg -> {
            errorMessage.put(msg.getField(), msg.getDefaultMessage());
        });
        return Result.error(CodeEnum.VALID_EXCEPTION.getMessage(), errorMessage);
    }

    /**
     * 数据校验异常(@Valid JSR303)
     *
     * @param e
     * @return
     */
    @ExceptionHandler(BindException.class)
    public Result handleBindException(BindException e) {
        BindingResult bindingResult = e.getBindingResult();
        Map<String, Object> errorMessage = new HashMap<>();
        bindingResult.getFieldErrors().forEach(msg -> {
            errorMessage.put(msg.getField(), msg.getDefaultMessage());
        });
        e.printStackTrace();
        return Result.error(CodeEnum.VALID_EXCEPTION.getMessage(), errorMessage);
    }


}
